package com.xlf.service.ai.utils;

import com.xlf.common.core.exception.BizException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;

@Slf4j
public class SseEmitterUtil {
    /**
     * 当前连接数
     */
    private static AtomicInteger count = new AtomicInteger(0);

    /**
     * 使用map对象，便于根据seeKey来获取对应的SseEmitter
     */
    private static Map<String, SseEmitter> sseEmitterMap = new ConcurrentHashMap<>();

    /**
     * 创建用户连接并返回 SseEmitter
     *
     * @param seeKey 用户ID
     * @return SseEmitter
     */
    public static SseEmitter connect(String seeKey) {
        // 设置超时时间，0表示不过期。默认30秒，超过时间未完成会抛出异常：AsyncRequestTimeoutException
        SseEmitter sseEmitter = new SseEmitter(120000L);

        // 注册回调
        sseEmitter.onCompletion(completionCallBack(seeKey));
        sseEmitter.onError(errorCallBack(seeKey));
        sseEmitter.onTimeout(timeoutCallBack(seeKey));
        // 设置前端的重试时间为1s
        try {
            sseEmitter.send(SseEmitter.event().reconnectTime(10000).data("连接成功"));
        } catch (IOException e) {
            e.printStackTrace();
            throw new BizException("连接失败！");
        }

        sseEmitterMap.put(seeKey, sseEmitter);
        // 数量+1
        count.getAndIncrement();
        log.info("创建新的sse连接，当前用户：{}", seeKey);
        return sseEmitter;
    }

    /**
     * 给指定用户发送信息
     */
    public static void sendMessage(String seeKey, String message) {
        if (sseEmitterMap.containsKey(seeKey)) {
            try {
                sseEmitterMap.get(seeKey).send(SseEmitter.event().id(seeKey).name("msg").data(message));
            } catch (IOException e) {
                log.error("用户[{}]推送异常:{}", seeKey, e.getMessage());
                removeUser(seeKey);
            }
        }
    }

    /**
     * 群发消息
     */
    public static void batchSendMessage(String wsInfo, List<String> ids) {
        ids.forEach(seeKey -> sendMessage(wsInfo, seeKey));
    }

    /**
     * 群发所有人
     */
    public static void batchSendMessage(String wsInfo) {
        sseEmitterMap.forEach((k, v) -> {
            try {
                v.send(wsInfo, MediaType.APPLICATION_JSON);
            } catch (IOException e) {
                log.error("用户[{}]推送异常:{}", k, e.getMessage());
                removeUser(k);
            }
        });
    }

    /**
     * 移除用户连接
     */
    public static void removeUser(String seeKey) {
        sseEmitterMap.remove(seeKey);
        // 数量-1
        count.getAndDecrement();
        log.info("移除用户：{}", seeKey);
    }

    /**
     * 获取当前连接信息
     */
    public static List<String> getIds() {
        return new ArrayList<>(sseEmitterMap.keySet());
    }

    /**
     * 获取当前连接数量
     */
    public static int getUserCount() {
        return count.intValue();
    }

    private static Runnable completionCallBack(String seeKey) {
        return () -> {
            log.info("结束连接：{}", seeKey);
            removeUser(seeKey);
        };
    }

    private static Runnable timeoutCallBack(String seeKey) {
        return () -> {
            log.info("连接超时：{}", seeKey);
            removeUser(seeKey);
        };
    }

    private static Consumer<Throwable> errorCallBack(String seeKey) {
        return throwable -> {
            log.info("连接异常：{}", seeKey);
            removeUser(seeKey);
        };
    }
}
